﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.AnalysisServices;
using Microsoft.Practices.Unity;
using Moop.Common;
using Moop.DataLayer.Olap.Service;
using Moop.UI.Common.Commands;
using Moop.UI.Common.ViewModels;
using Moop.UI.Exceptions;
using Moop.UI.UIServices;
using Moop.UI.Utils;

namespace Moop.UI.ViewModels
{
	public class ServerViewModel : BaseViewModel
	{

		#region Commands

		public ICommand SetServerCommand { get; set; }

		#endregion


		#region Properties

		private string _serverConnString;
		public string ServerConnString
		{
			get { return _serverConnString; }
			set { _serverConnString = value; base.OnPropertyChanged("ServerConnString"); }
		}

		private bool _IsCubeSelected;
		public bool IsCubeSelected
		{
			get
			{
				if (string.IsNullOrEmpty(SelectedCubeName))
				{
					return false;
				}
				else
				{
					return true;
				}
			}
			set { _IsCubeSelected = value; base.OnPropertyChanged("IsCubeSelected"); }
		}


		private string _SelectedCubeName;
		public string SelectedCubeName
		{
			get { return _SelectedCubeName; }
			set
			{
				_SelectedCubeName = value;

				#region Set Cube Tree - Extract to method later

				if (!string.IsNullOrEmpty(_SelectedCubeName))
					CubeDimensions = new ObservableCollection<ICubeDimension>(OlapDb.Cubes[_SelectedCubeName].CubeDimensions.Values);

				#endregion

				IsCubeSelected = true;
				base.OnPropertyChanged("SelectedCubeName");
			}
		}

		private bool _CubesLoaded;
		public bool CubesLoaded
		{
			get 
			{
				if (_Cubes != null && _Cubes.Count > 0) { return true; } else { return false; }
			}
			set { _CubesLoaded = value;  base.OnPropertyChanged("CubesLoaded");}

		}

		private ObservableCollection<ICube> _Cubes;
		public ObservableCollection<ICube> Cubes
		{
			get 
			{
				return _Cubes; 
			}
			set 
			{
				_Cubes = value; base.OnPropertyChanged("Cubes");
				if (_Cubes != null && _Cubes.Count > 0) { CubesLoaded = true; }
			}
		}

		private ObservableCollection<ICubeDimension> _CubeDimensions;
		public ObservableCollection<ICubeDimension> CubeDimensions
		{
			get
			{
				if (_CubeDimensions != null)
					return new ObservableCollection<ICubeDimension>(_CubeDimensions.OrderBy(p => p.Name));
				else return null;
			}
			set { _CubeDimensions = value; base.OnPropertyChanged("CubeDimensions"); }
		}

		private ObservableCollection<ICubeMeasure> _CubeMeasures;
		public ObservableCollection<ICubeMeasure> CubeMeasures
		{
			get { return _CubeMeasures; }
			set { _CubeMeasures = value; base.OnPropertyChanged("CubeMeasures"); }
		}

		private ObservableCollection<ICubeDimensionSet> _CubeNamedSets;
		public ObservableCollection<ICubeDimensionSet> CubeNamedSets
		{
			get { return _CubeNamedSets; }
			set { _CubeNamedSets = value; base.OnPropertyChanged("CubeNamedSets"); }
		}

		private IOlapDatabase _OlapDb;
		public IOlapDatabase OlapDb
		{
			get { return _OlapDb; }
			set { _OlapDb = value; base.OnPropertyChanged("OlapDb"); }
		}

		private IOlapDataService _Server;
		public IOlapDataService Server
		{
			get { return _Server; }
			set { _Server = value; base.OnPropertyChanged("Server"); }
		}

		#endregion

		//Ctor
		public ServerViewModel()
		{
			SetServerCommand = new RelayCommand(GetDatabaseAsync, CanGetDatabase);
			ServerConnString = "Data Source=.;Catalog=Adventure Works DW 2008R2;";//TODO: remove later and store somewhere in history file etc
		}


		private bool CanGetDatabase(object param)
		{
			if (IsBusy)
				return false;
			else
				return true;
		}


		private void GetDatabaseAsync(object param)
		{
			IsBusy = true;
			ConnectionInfo csBuilder = null;
			try
			{
				csBuilder = new ConnectionInfo(ServerConnString);
				IOlapDataService olapDataService = TypeContainer.Instance.Resolve<IOlapDataService>();
				olapDataService.DastabaseName = csBuilder.Catalog;
				olapDataService.OlapMetaDataService.ConnectionString = ServerConnString;
				IAsyncResult ar = olapDataService.BeginPopulate(null, new AsyncCallback(GetDatabaseAsyncCallBack), olapDataService);
			}
			catch (Exception e)
			{
				MessageBox.Show(e.Message);
				IsBusy = false;
			}
		}



		public void GetDatabaseAsyncCallBack(IAsyncResult result)
		{
			if (((Task<IOlapDatabase>)result).IsFaulted)
			{
				AggregateException aggEx = ((Task<IOlapDatabase>)result).Exception.Flatten();
				FlattenedAggregateException flatAggEx = aggEx.HadleAggregateException();
				MessageBox.Show(flatAggEx.Message + Environment.NewLine + flatAggEx.StackTrace, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
			}
			else
			{
				IOlapDataService c = (IOlapDataService)result.AsyncState;
				OlapDb = c.EndPopulate(result);
				Cubes = new ObservableCollection<ICube>(OlapDb.Cubes.Values);
			}
			IsBusy = false;
		}


		internal TreeView GetCubeTreeView()
		{
			UIService uiService = new UIService();
			return uiService.GetCubeTreeView(Cubes, SelectedCubeName);
		}
	}

}
